﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SCGILite.NetLib;
using System.IO;
using System.Net;
using System.Threading;
using SCGILite.Helper;

namespace SCGILite.SCgi
{
    public class SCgiSession : IAppSession
    {
        public int StatuesCode
        {
            get { return Response.StatuesCode; }
            set { Response.StatuesCode = value; }
        }
        public virtual void OnSCgiHeaderReady()
        {
        }
        public virtual void OnSCgiBodyReady()
        {
        }
        public virtual void OnSCgiBodyData(byte[] buf, int offset, int len)
        {
        }
        public virtual void OnClose()
        {
        }
        public virtual void OnErr(Exception e)
        {
        }
        public void _OnErr(Exception e)
        {
            if (this.Response.isEndResponse)
                return;
            ActionHelper.SafeExcute(OnErr, e);
        }
        public SCgiSession(ISocketSession tcp)
        {
            _tcp = tcp;
            _Request = new SCgiRequest(OnHead, OnBodyData, OnReciveComplate);
            _Response = new SCgiResponse(SendResponse, Close);
            isAsync = false;
        }
        public void OnReciveComplated(byte[] buf, int offset, int len)
        {
            if (this.Response.isEndResponse)
                return;
            try
            {
                Request.Write(buf, offset, len);
            }
            catch
            {
                this.Close();
            }
        }

        public void SendResponse(INetOutputStream ms)
        {
            tcp.SendResponse(ms);
        }
        public int _close = 0;
        public void Close()
        {
            try
            {
                tcp.Close();
            }
            catch
            {
            }
            if (Interlocked.Exchange(ref _close, 1) == 0)
                OnClose();
        }
        
        public bool isClose
        {
            get { return (_close != 0); }
        }

        ISocketSession _tcp;
        public ISocketSession tcp
        {
            get { return _tcp; }
        }

        public object Tag { get; set; }
        SCgiRequest _Request;
        SCgiResponse _Response;
        public SCgiRequest Request { get { return _Request; } }
        SCgiResponse Response { get { return _Response; } }
        public bool isAsync { get; set; }
        
        void OnHead()
        {
            try
            {
                OnSCgiHeaderReady();
            }
            catch(Exception e)
            {
                _OnErr(e);
            }
        }

        void OnBodyData(byte[] buf, int offset, int len)
        {
            try
            {
                OnSCgiBodyData(buf, offset, len);
            }
            catch(Exception e)
            {
                _OnErr(e);
            }
        }
        void OnReciveComplate()
        {
            try
            {
                OnSCgiBodyReady();
            }
            catch (Exception e)
            {
                _OnErr(e);
            }

            if (!isAsync)
            {
                this.EndResponse();
            }
        }

        public void StartSession()
        {
        }
        public void ResponseHeaders(IDictionary<string, string> Headers)
        {
            this.Response.SetResponseHeaders(Headers);
        }
        public void ResponseBody(INetOutputStream body)
        {
            this.Response.Response(body);
        }
        public void EndResponse()
        {
            this.Response.EndResponse();
        }
    }
}
